package org.langcom.crypt;

import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.util.logging.Logger;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500PrivateCredential;


/**
 * The <code>ObjectSigner</code> wraps an object signing operation in one
 * class. It has only useful method {@link #sign(Serializable)}. This ,ethod
 * should be useed to sign any object. As result the method returns a signature
 * as a <code>{@link com.kazinfotel.auction.com.DigitalSignature}</code>
 * object.
 * 
 * @see com.kazinfotel.auction.com.DigitalSignature
 */
public final class ObjectSigner {

	public static final String DEAFULT_SIGNATURE_ALGORITHM = "SHA1withDSA";

	private final static Logger LOG = Logger.getLogger(ObjectSigner.class
			.getName());

	private final Signature engine;

	private final X500PrivateCredential credential;

	public static ObjectSigner getSigner(Subject subject, Signature engine) {
		LOG.fine("Subject to use while signing : " + subject);
		X500PrivateCredential credential = (X500PrivateCredential) subject
				.getPrivateCredentials().iterator().next();
		return new ObjectSigner(credential, engine);
	}

	public static ObjectSigner getSigner(Subject subject)
			throws NoSuchAlgorithmException {
		assert (subject != null) : "Subject must not be null!";
		return getSigner(subject, Signature
				.getInstance(DEAFULT_SIGNATURE_ALGORITHM));
	}

	/**
	 * Constructs new signer using concrete private key and signature engine.
	 * 
	 * @param privateKey
	 *            the private key to use while signing.
	 * @param engine
	 *            the signature engine to use.
	 */
	public ObjectSigner(X500PrivateCredential credential, Signature engine) {
		assert (credential != null) && (engine != null);
		this.credential = credential;
		this.engine = engine;
	}

	/**
	 * Returns a signing engine's algorithm name.
	 * 
	 * @return the algorithm to be used while signing.
	 */
	public String getSignatureAlgorithm() {
		return engine.getAlgorithm();
	}

	/**
	 * Signs the object using stored private key and signature engine.
	 * 
	 * @param obj
	 *            the object to sign.
	 * @return a digital signature of this object.
	 * @throws InvalidKeyException
	 *             may be rethrown bu signing engine.
	 * @throws SignatureException
	 *             may be rethrown bu signing engine.
	 */
	public final DigitalSignature sign(Serializable obj)
			throws InvalidKeyException, SignatureException {
		return new DigitalSignature(credential, obj, engine);
	}
	
	public final DigitalSignature signBytes(byte[] toSign)
			throws InvalidKeyException, SignatureException {
		return new DigitalSignature(credential, toSign, engine);
	}


}